package zcatt.examples.swt.widgets;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class BusyIndicatorTab extends WidgetTab {
	Text resultText;

	public BusyIndicatorTab(WidgetExample example) {
		super(example);
	}

	@Override
	public void dispose() {
	}

	@Override
	public String getText() {
		return "BusyIndicatorTab";
	}

	@Override
	public String getCategory() {
		return "Misc";
	}

	@Override
	public String getDescription() {
		return "show BusyIndicator";
	}

	@Override
	public void createWidget(Composite parent) {
		Composite comp = new Composite(parent, SWT.NONE);
		comp.setLayout(new GridLayout());
		
		resultText = new Text(comp, SWT.MULTI);
		resultText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		resultText.append("BusyIndicator example.\n");
		
		Group grp;
		Button btn;
		
		grp= new Group(comp, SWT.NONE);
		grp.setText("BusyIndicator, longJob in worker thread");
		grp.setLayout(new GridLayout());
		
		btn = new Button(grp, SWT.PUSH);
		btn.setText("trigger");
		btn.addSelectionListener(SelectionListener.widgetSelectedAdapter(event->{
			resultText.append("UI threadId="+Thread.currentThread().getId()+"\n");
			Runnable job = new Runnable() {
				@Override
				public void run() {
					Shell shell = resultText.getShell();
					Display display = shell.getDisplay();
					Thread thread = new Thread(new LongJob(resultText.getDisplay(), resultText));
					thread.start();
					
					//此消息循环是等待thread结束前持续分发event, 避免ui阻塞
					while(thread.isAlive() && !shell.isDisposed())
					{
						if (!display.readAndDispatch())
							display.sleep();						
					}
				}
				
			};
			BusyIndicator.showWhile(resultText.getDisplay(), job);	
			
		}));

		grp= new Group(comp, SWT.NONE);
		grp.setText("BusyIndicator, longJob in UI thread");		//zf, 会阻塞UI
		grp.setLayout(new GridLayout());
		
		btn = new Button(grp, SWT.PUSH);
		btn.setText("trigger");
		btn.addSelectionListener(SelectionListener.widgetSelectedAdapter(event->{
			resultText.append("UI threadId="+Thread.currentThread().getId()+"\n");
			Runnable job = new LongJob(resultText.getDisplay(), resultText);				
			BusyIndicator.showWhile(resultText.getDisplay(), job);	
		}));
	}

	@Override
	public void createControlPanel(Composite parent) {
	}

	//.BusyIndicator.showWhile()是直接调用longJob.run(),故run()执行完毕之前不会返回. 
	//	故当BusyIndicator.showWhile()运行在UI thread时, longJob.run()应当避免UI阻塞/消息循环阻塞.
	//.
	class LongJob implements Runnable
	{		
		Display display;
		Text text;
		int i;
		long tId;
		
		public LongJob(Display display, Text text)
		{
			this.display = display;
			this.text = text;			
			i = 5;
		}

		public boolean isDone()
		{
			return i < 0;
		}
		
		@Override
		public void run() {
			tId = Thread.currentThread().getId();
			display.syncExec(()-> text.append("longJob start. threadId="+tId+"\n"));
			for(i = 5; i >= 0; i--)
			{
				try {
					Thread.sleep(1000);
				}
				catch(Exception e)
				{
					//break;
				}
				display.syncExec(()-> text.append("count down: "+ i +"\n"));
			}
			
			display.syncExec(()-> text.append("longJob over.\n"));
		}		
	}
}
